package com.zxy.study.utils

import android.content.Context
import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.SensorManager
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import com.lahm.library.CheckResult
import com.lahm.library.CommandUtil
import com.lahm.library.EmulatorCheckCallback
import java.io.File
import java.util.*

/**
 * @author : Shonn.Zhang
 * @email  : shonn.zhang@mart.blue
 * @time   : 2021/6/18 14:51
 * @desc   :
 */
object BlueEmulatorDetectUtil {

    /**
     * 检测是否运行在模拟器
     */
    fun checkIsRunningInEmulator(context: Context, callback: EmulatorCheckCallback?): Boolean {
        return readSysProperty(context, callback)
    }

    private fun readSysProperty(context: Context, callback: EmulatorCheckCallback?): Boolean {

        //检测是不是蓝叠模拟器
        if (isBlueStacks()) {
            callback?.findEmulator("isBlueStacks = true")
            return true
        }

        var suspectCount = 0

        //检测硬件名称
        val hardwareResult = checkFeaturesByHardware()
        when (hardwareResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("hardware = " + hardwareResult.value)
                return true
            }
        }

        //检测渠道
        val flavorResult = checkFeaturesByFlavor()
        when (flavorResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("flavor = " + flavorResult.value)
                return true
            }
        }

        //检测设备型号
        val modelResult = checkFeaturesByModel()
        when (modelResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("model = " + modelResult.value)
                return true
            }
        }

        //检测硬件制造商
        val manufacturerResult = checkFeaturesByManufacturer()
        when (manufacturerResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("manufacturer = " + manufacturerResult.value)
                return true
            }
        }

        //检测主板名称
        val boardResult = checkFeaturesByBoard()
        when (boardResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("board = " + boardResult.value)
                return true
            }
        }

        //检测主板平台
        val platformResult = checkFeaturesByPlatform()
        when (platformResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> ++suspectCount
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("platform = " + platformResult.value)
                return true
            }
        }

        //检测基带信息
        val baseBandResult = checkFeaturesByBaseBand()
        when (baseBandResult.result) {
            CheckResult.RESULT_MAYBE_EMULATOR -> suspectCount += 2 //模拟器基带信息为null的情况概率相当大
            CheckResult.RESULT_EMULATOR -> {
                callback?.findEmulator("baseBand = " + baseBandResult.value)
                return true
            }
        }

        //检测传感器数量
        val sensorNumber = getSensorNumber(context)
        if (sensorNumber <= 14) ++suspectCount

        //检测已安装第三方应用数量
        val userAppNumber = getUserAppNumber()
        if (userAppNumber <= 5) ++suspectCount

        //检测是否支持闪光灯
        val supportCameraFlash = supportCameraFlash(context)
        if (!supportCameraFlash) ++suspectCount
        //检测是否支持相机
        val supportCamera = supportCamera(context)
        if (!supportCamera) ++suspectCount
        //检测是否支持蓝牙
        val supportBluetooth = supportBluetooth(context)
        if (!supportBluetooth) ++suspectCount

        //检测光线传感器
        val hasLightSensor = hasLightSensor(context)
        if (!hasLightSensor) ++suspectCount

        //检测进程组信息
        val cgroupResult = checkFeaturesByCgroup()
        if (cgroupResult.result == CheckResult.RESULT_MAYBE_EMULATOR) ++suspectCount

        //检测cpu架构
        val cpuAbi = checkCpuAbi()
        if (cpuAbi.result == CheckResult.RESULT_MAYBE_EMULATOR) suspectCount += 2

        if (callback != null) {
            val stringBuffer = StringBuffer("Test start")
                    .append("\r\n").append("hardware = ").append(hardwareResult.value)
                    .append("\r\n").append("flavor = ").append(flavorResult.value)
                    .append("\r\n").append("model = ").append(modelResult.value)
                    .append("\r\n").append("manufacturer = ").append(manufacturerResult.value)
                    .append("\r\n").append("board = ").append(boardResult.value)
                    .append("\r\n").append("platform = ").append(platformResult.value)
                    .append("\r\n").append("baseBand = ").append(baseBandResult.value)
                    .append("\r\n").append("sensorNumber = ").append(sensorNumber)
                    .append("\r\n").append("userAppNumber = ").append(userAppNumber)
                    .append("\r\n").append("supportCamera = ").append(supportCamera)
                    .append("\r\n").append("supportCameraFlash = ").append(supportCameraFlash)
                    .append("\r\n").append("supportBluetooth = ").append(supportBluetooth)
                    .append("\r\n").append("hasLightSensor = ").append(hasLightSensor)
                    .append("\r\n").append("cgroupResult = ").append(cgroupResult.value)
                    .append("\r\n").append("abi = ").append(cpuAbi.value)
                    .append("\r\n").append("suspectCount = ").append(suspectCount)
            callback.findEmulator(stringBuffer.toString())
        }
        //嫌疑值大于3，认为是模拟器
        return suspectCount > 3
    }

    private fun getUserAppNum(userApps: String): Int {
        if (TextUtils.isEmpty(userApps)) return 0
        val result = userApps.split("package:".toRegex()).toTypedArray()
        return result.size
    }

    private fun getProperty(propName: String): String? {
        val property = CommandUtil.getSingleInstance().getProperty(propName)
        return if (TextUtils.isEmpty(property)) null else property
    }

    /**
     * 特征参数-硬件名称
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByHardware(): CheckResult {
        val hardware = getProperty("ro.hardware")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val result: Int
        val tempValue = hardware.toLowerCase(Locale.ROOT)
        result = when (tempValue) {
            "ttvm",  //天天模拟器
            "nox",   //夜神模拟器（旧版）
            "cancro",//网易MUMU模拟器
            "intel", //逍遥模拟器
            "vbox",
            "vbox86", //腾讯手游助手
            "android_x86",//雷电模拟器
            "windroye",//文卓爷模拟器
            "droid4x"  //海马玩模拟器
            -> CheckResult.RESULT_EMULATOR
            else -> CheckResult.RESULT_UNKNOWN
        }
        return CheckResult(result, hardware)
    }

    /**
     * 特征参数-渠道
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByFlavor(): CheckResult {
        val flavor = getProperty("ro.build.flavor")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val tempValue = flavor.toLowerCase(Locale.ROOT)
        val result = when {
            tempValue.contains("vbox")
                    || tempValue.contains("sdk_gphone") -> CheckResult.RESULT_EMULATOR
            else -> CheckResult.RESULT_UNKNOWN
        }
        return CheckResult(result, flavor)
    }

    /**
     * 特征参数-设备型号
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByModel(): CheckResult {
        val model = getProperty("ro.product.model")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val tempValue = model.toLowerCase(Locale.ROOT)

        val result = when {
            tempValue.contains("google_sdk")
                    || tempValue.contains("emulator")
                    || tempValue.contains("android sdk built for x86")
                    || tempValue.equals("Windroye", true)
                    || tempValue.equals("Droid4X", true) -> CheckResult.RESULT_EMULATOR
            else -> CheckResult.RESULT_UNKNOWN
        }
        return CheckResult(result, model)
    }

    /**
     * 特征参数-硬件制造商
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByManufacturer(): CheckResult {
        val manufacturer = getProperty("ro.product.manufacturer")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val tempValue = manufacturer.toLowerCase(Locale.ROOT)

        val result = when {
            tempValue.contains("genymotion")
                    || tempValue.contains("netease")//网易MUMU模拟器
                    || tempValue.equals("Windroye", true)
                    || tempValue.equals("Droid4X", true) -> CheckResult.RESULT_EMULATOR
            else -> CheckResult.RESULT_UNKNOWN
        }
        return CheckResult(result, manufacturer)
    }

    /**
     * 特征参数-主板名称
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByBoard(): CheckResult {
        val board = getProperty("ro.product.board")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val tempValue = board.toLowerCase(Locale.ROOT)

        val result = when {
            tempValue.contains("android")
                    || tempValue.contains("goldfish") -> CheckResult.RESULT_EMULATOR
            else -> CheckResult.RESULT_UNKNOWN
        }

        return CheckResult(result, board)
    }

    /**
     * 特征参数-主板平台
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByPlatform(): CheckResult {
        val platform = getProperty("ro.board.platform")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val tempValue = platform.toLowerCase(Locale.ROOT)

        val result = if (tempValue.contains("android")) CheckResult.RESULT_EMULATOR
        else CheckResult.RESULT_UNKNOWN
        return CheckResult(result, platform)
    }

    /**
     * 特征参数-基带信息
     *
     * @return 0表示可能是模拟器，1表示模拟器，2表示可能是真机
     */
    private fun checkFeaturesByBaseBand(): CheckResult {
        val baseBandVersion = getProperty("gsm.version.baseband")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)

        val result = if (baseBandVersion.contains("1.0.0.0")) CheckResult.RESULT_EMULATOR
        else CheckResult.RESULT_UNKNOWN
        return CheckResult(result, baseBandVersion)
    }

    /**
     * 获取传感器数量
     */
    private fun getSensorNumber(context: Context): Int {
        val sm = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        return sm.getSensorList(Sensor.TYPE_ALL).size
    }

    /**
     * 获取已安装第三方应用数量
     */
    private fun getUserAppNumber(): Int {
        val userApps = CommandUtil.getSingleInstance().exec("pm list package -3")
        return getUserAppNum(userApps)
    }

    /**
     * 是否支持相机
     */
    private fun supportCamera(context: Context): Boolean {
        return context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
    }

    /**
     * 是否支持闪光灯
     */
    private fun supportCameraFlash(context: Context): Boolean {
        return context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
    }

    /**
     * 是否支持蓝牙
     */
    private fun supportBluetooth(context: Context): Boolean {
        return context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
    }

    /**
     * 判断是否存在光传感器来判断是否为模拟器
     * 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
     *
     * @return false为模拟器
     */
    private fun hasLightSensor(context: Context): Boolean {
        val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) //光线传感器
        return null != sensor
    }

    /**
     * 特征参数-进程组信息
     */
    private fun checkFeaturesByCgroup(): CheckResult {
        val filter = CommandUtil.getSingleInstance().exec("cat /proc/self/cgroup")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        return CheckResult(CheckResult.RESULT_UNKNOWN, filter)
    }

    /**
     * 根据共享目录文件路径判断是否是蓝叠模拟器，拿不到路径就当做不是
     */
    private fun isBlueStacks(): Boolean {
        try {
            val sharedFolder = File((Environment.getExternalStorageDirectory().toString()
                    + File.separatorChar).toString() + "windows"
                    + File.separatorChar.toString() + "BstSharedFolder")
            return sharedFolder.exists()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    /**
     * 检测cpu架构，模拟器一般都是x86
     */
    private fun checkCpuAbi(): CheckResult {
        val abi = getProperty("ro.product.cpu.abi")
                ?: return CheckResult(CheckResult.RESULT_MAYBE_EMULATOR, null)
        val result = if (abi.contains("x86")) CheckResult.RESULT_MAYBE_EMULATOR
        else CheckResult.RESULT_UNKNOWN

        return CheckResult(result, abi)
    }
}